// PPCSystem.v - Instantiates an edk project and exports a memory bus
// Copyright 2005 Pico Computing, Inc.

`include "PicoDefines.v"

module PPCSystem(
   input         Clk, 
   input         Clk200, 
   input         Rst, 
   output [15:0] DataIn, 
   input  [15:0] DataOut,
   output        CPLD_PEEKABOO_PPC, //hrgt:Jun 6, 2007 for standalone
   output        CPLD_RELOAD_PPC,   //hrgt:Jun 6, 2007 for standalone
   input  [25:0] FLASH_AIN,  //JBC June 8, changed from output to input //hrgt:Jun 6, 2007 for standalone
   output        CPUMemMaster, 
   output [31:0] MemAddrMaster, 
   output        MemReadMaster, 
   output        MemWriteMaster, 
   output        AttrReadMaster,
   output        AttrWriteMaster,
   output        IOReadMaster,
   output        IOWriteMaster,
   input [`PCMCIA_ADR_LINES-1:0] IOAddr,
   input         IORead,
   input         CFIORead,
   input         IOWrite,
   input         CFIOWrite,                //DRP: 1/10/07 corrected keyhole versus CPUMemMaster problem
   input         MemWait,
   input  [15:0] CFDataIn,
   output [15:0] CFDataOut,
   output [12:0] RamAddr,
   input  [0:31] RamDIn,
   output [0:31] RamDOut,
   output [0:31] RamDT,
   output [0:3]  RamDM,
   output        RamWE,
   output        RamClkE,
   output        RamCS,
   output        RamCAS,
   output        RamRAS,
   output        RamClk,
   output [0:1]  RamBA,
   input  [4:1]  GPIO_IN,                  //4:1 to mesh with Jason's LBBase...
   output [4:1]  GPIO_OUT,
   output [4:1]  GPIO_TRIS,                //JBC - 2/22/07 - changed names to GPIO_IN, GPIO_OUT, GPIO_TRIS
   output        DcmsLocked,
   input         FlashReady,
   input         StandaloneSw,
   
   `ifdef ENABLE_ETH //{
      output      ETHER_GTX_CLK,
      output      ETHER_COMA,
      output      ETHER_MDC,
      input       ETHER_MDIO_I,
      output      ETHER_MDIO_O,
      output      ETHER_MDIO_T,
      output      ETHER_RESET,
      input       ETHER_RX_CLK,
      input       ETHER_RX_CTL,
      input       ETHER_RX_ER,
      input [7:0] ETHER_RX,
      input       ETHER_TX_CLK,
      output      ETHER_TX_EN,
      output      ETHER_TX_ER,
      output [7:0] ETHER_TX,
   `endif
   
   output [127:0] test_pins,
   output         OPB_Clk, 
   output         OPB_Clk90,
   output         OPB_Rst,
   output [0:31]  OPB_ABus,
   output [0:3]   OPB_BE,
   output [0:31]  OPB_DBus,
   output         OPB_RNW,
   output         OPB_select,
   output         OPB_seqAddr,
   input  [31:0]  Sl_DBus_ext,
   input          Sl_errAck_ext,
   input          Sl_retry_ext,
   input          Sl_toutSup_ext,
   input          Sl_xferAck_ext
);

wire [15:0] KeyholeDataOut;

//assign DcmsLocked = 1'b1;

wire GPIO_0;
wire GPIO_2;
wire GPIO_3;

wire Clker;
BUFG CLKBUFG(
   .I(Clk),
   .O(Clker)
);

wire [0:31] Sl_DBus;
wire Sl_errAck;
wire Sl_retry;
wire Sl_toutSup;
wire Sl_xferAck;

wire [0:31] UM_Sl_DBus;
wire UM_Sl_errAck;
wire UM_Sl_retry;
wire UM_Sl_toutSup;
wire UM_Sl_xferAck;

wire [0:31] Ctrl_Sl_DBus;
wire Ctrl_Sl_errAck;
wire Ctrl_Sl_retry;
wire Ctrl_Sl_toutSup;
wire Ctrl_Sl_xferAck;

wire [0:31] MB_Sl_DBus; //hrgt: Jun 6th, names consistent with E-14
wire MB_Sl_errAck;
wire MB_Sl_retry;
wire MB_Sl_toutSup;
wire MB_Sl_xferAck;

`ifdef ENABLE_KEYHOLE
wire [0:31] Kh_Sl_DBus;
wire Kh_Sl_errAck;
wire Kh_Sl_retry;
wire Kh_Sl_toutSup;
wire Kh_Sl_xferAck;
`endif

wire dcm_rst;
SRL16 RESET_SRL(
   .Q(dcm_rst),
   .A0(1'b1),
   .A1(1'b0),
   .A2(1'b0),
   .A3(1'b0),
   .CLK(Clker),
   .D(1'b0)
);
//synthesis attribute INIT of RESET_SRL is 16'hFFFF;
//synthesis translate_off
defparam RESET_SRL.INIT = 16'hFFFF;
//synthesis translate_on

wire proc_clk_s;
wire sys_clk_s;
wire opb_clk_s;
wire opb_clk90_s;
wire ppc_dcm_fb;
wire ppc_dcm_locked;

/*
//BUFG ppc_fb_bufg(.I(opb_clk_s), .O(ppc_dcm_fb));
BUFG ppc_opb_bufg(
   .I(opb_clk_s_unbuf),
   .O(opb_clk_s)
);
BUFG ppc_opb90_bufg(
   .I(opb_clk90_s_unbuf),
   .O(opb_clk90_s)
);
BUFG ppc_sys_bufg(
   .I(sys_clk_s_unbuf),
   .O(sys_clk_s)
);
BUFG ppc_proc_bufg(
   .I(proc_clk_s_unbuf),
   .O(proc_clk_s)
);

assign DcmsLocked = ppc_dcm_locked;

wire dcm_rst;
SRL16 RESET_SRL(
   .Q(dcm_rst),
   .A0(1'b1),
   .A1(1'b0),
   .A2(1'b0),
   .A3(1'b0),
   .CLK(Clker),
   .D(1'b0)
);
//synthesis attribute INIT of RESET_SRL is 16'hFFFF;
//synthesis translate_off
defparam RESET_SRL.INIT = 16'hFFFF;
//synthesis translate_on

DCM_BASE ppc_dcm(
   .CLKIN(Clker), // 50MHz
   .CLK0(opb_clk_s_unbuf),
   .CLK90(opb_clk90_s_unbuf),
   .CLK2X(sys_clk_s_unbuf),
   .CLKFX(proc_clk_s_unbuf),
   .CLKFB(opb_clk_s),
   .LOCKED(ppc_dcm_locked),
   .RST(dcm_rst)
);

//defparam DCM_PS_inst.CLKDV_DIVIDE = 2.0;               // Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
                                                         // 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
defparam ppc_dcm.CLKFX_DIVIDE = 1;                       // Can be any integer from 1 to 32
defparam ppc_dcm.CLKFX_MULTIPLY = 6;                     // Can be any integer from 2 to 32
defparam ppc_dcm.CLKIN_DIVIDE_BY_2 = "FALSE";            // TRUE/FALSE to enable CLKIN divide by two feature
defparam ppc_dcm.CLKIN_PERIOD = 20.0;                    // Specify period of input clock in ns from 1.25 to 1000.00
defparam ppc_dcm.CLKOUT_PHASE_SHIFT = "NONE";            // Specify phase shift mode of NONE or FIXED
defparam ppc_dcm.CLK_FEEDBACK = "1X";                    // Specify clock feedback of NONE, 1X or 2X
defparam ppc_dcm.DCM_PERFORMANCE_MODE = "MAX_SPEED";     // Can be MAX_SPEED or MAX_RANGE
//defparam ppc_dcm.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS"; // SOURCE_SYNCHRONOUS, SYSTEM_SYNCHRONOUS or  an integer from 0 to 15
defparam ppc_dcm.DFS_FREQUENCY_MODE = "HIGH";            // LOW or HIGH frequency mode for frequency synthesis
//defparam ppc_dcm.DLL_FREQUENCY_MODE = "LOW";           // LOW, HIGH, or HIGH_SER frequency mode for DLL
defparam ppc_dcm.DUTY_CYCLE_CORRECTION = "TRUE";         // Duty cycle correction, TRUE or FALSE
defparam ppc_dcm.FACTORY_JF = 16'hf0f0;                  // FACTORY JF suggested to be set to 16'hc080 for LOW
                                                         // DLL_FREQUENCY_MODE and to 16'hf0f0 for HIGH DLL_FREQUENCY_MODE
defparam ppc_dcm.PHASE_SHIFT = 0;                        // Amount of fixed phase shift from -255 to 1023
defparam ppc_dcm.STARTUP_WAIT = "FALSE";                 // Delay configuration DONE until DCM LOCK, TRUE/FALSE
*/


assign GPIO_OUT[4:1] = {1'b0, GPIO_2, 1'b0, 1'b0};
assign GPIO_0 = GPIO_IN[1];
//assign GPIO_3 = GPIO_IN[4]; - JBC - 2/22/07 - this is O/E pin for R-232 transiever - it is set above
assign GPIO_TRIS[4:1] = {1'b0, 1'b0, 1'b1, 1'b1};

`define C_OPB_AWIDTH 32
`define C_OPB_DWIDTH 32

system edk_blackbox (
/*      .proc_clk_s  (proc_clk_s),
      .opb_clk_s   (opb_clk_s),
      .opb_clk90_s (opb_clk90_s),
      .sys_clk_s   (sys_clk_s),
*/
      .GPIO_0 (GPIO_0),
      .GPIO_2 (GPIO_2),
  //    .GPIO_3 (GPIO_3),

      .RAM_A    (RamAddr),
      .RAM_DM   (RamDM),
      .RAM_WE   (RamWE),
      .RAM_CLKE (RamClkE),
      .RAM_CS   (RamCS),
      .RAM_CAS  (RamCAS),
      .RAM_RAS  (RamRAS),
      .RAM_CLK  (RamClk),
      .RAM_BA   (RamBA),
      .RAM_D_I  (RamDIn),
      .RAM_D_O  (RamDOut),
      .RAM_D_T  (RamDT),
`ifdef ENABLE_ETH
     .ETHER_GTX_CLK (ETHER_GTX_CLK),
//   .ETHER_25MHZ   (ETHER_25MHZ), 
     .ETHER_COMA    (ETHER_COMA),  
     .ETHER_MDC     (ETHER_MDC),   
     .ETHER_MDIO_I  (ETHER_MDIO_I),  
     .ETHER_MDIO_O  (ETHER_MDIO_O),  
     .ETHER_MDIO_T  (ETHER_MDIO_T),  
     .ETHER_RESET   (ETHER_RESET), 
     .ETHER_RX_CLK  (ETHER_RX_CLK),
     .ETHER_RX_CTL  (ETHER_RX_CTL),
     .ETHER_RX_ER   (ETHER_RX_ER), 
     .ETHER_RX      (ETHER_RX),    
     .ETHER_TX      (ETHER_TX),    
     .ETHER_TX_CLK  (ETHER_TX_CLK),
     .ETHER_TX_EN   (ETHER_TX_EN),
     .ETHER_TX_ER   (ETHER_TX_ER), 
     .CLOCK_3       (Clk),           //JBC - 2/27/07 - uncommented line and only passed if ethernet is enabled
`endif // ENABLE_ETH
      
      .CLK50       (Clker),
      .OPB_Clk     (OPB_Clk),
      .OPB_Clk90   (OPB_Clk90),
      .OPB_Rst     (OPB_Rst),
      .OPB_ABus    (OPB_ABus),
      .OPB_BE      (OPB_BE),
      .OPB_DBus    (OPB_DBus),
      .OPB_RNW     (OPB_RNW),
      .OPB_select  (OPB_select),
      .OPB_seqAddr (OPB_seqAddr),
      .Sl_DBus     (Sl_DBus),
      .Sl_errAck   (Sl_errAck),
      .Sl_retry    (Sl_retry),
      .Sl_toutSup  (Sl_toutSup),
      .Sl_xferAck  (Sl_xferAck),
      .dcms_locked (DcmsLocked),
      .dcm_rst     (dcm_rst),
      .SYS_RST     (Rst)
    );

//--------------OPB Control Register Decoder-----------------------------
/*
 * control module which allows software on the CPU to toggle the opb_flash_en
 * line which switches flash rom control to the CPU and allows CPU software to
 * peekaboo at what image is currently loaded which is useful for booting
 * proper elf images in the boot loader.
 */

//wire [63:0] OPBCtrl_test_pins;
OPBCtrl
#(
   .C_OPB_AWIDTH(32),
   .C_OPB_DWIDTH(32),
   .C_BASEADDR  (`OPB_CTRL_BASEADDR),
   .C_HIGHADDR  (`OPB_CTRL_HIGHADDR)
)
OPBCtrl(
   .opb_flash_en (CPUMemMaster),
   .OPB_Clk      (OPB_Clk),               // opb -> slave bus
   .OPB_Rst      (OPB_Rst),
   .OPB_ABus     (OPB_ABus),
   .OPB_BE       (OPB_BE),
   .OPB_DBus     (OPB_DBus),
   .OPB_RNW      (OPB_RNW),
   .OPB_select   (OPB_select),
   .OPB_seqAddr  (OPB_seqAddr),
   .Sl_DBus      (Ctrl_Sl_DBus),          // slave -> opb bus
   .Sl_errAck    (Ctrl_Sl_errAck),
   .Sl_retry     (Ctrl_Sl_retry),
   .Sl_toutSup   (Ctrl_Sl_toutSup),
   .Sl_xferAck   (Ctrl_Sl_xferAck),
   .DcmsLocked   (DcmsLocked),
   .FlashReady   (FlashReady),
   .StandaloneSw (StandaloneSw)
   //,.test_pins (OPBCtrl_test_pins)
);

//--------------OPB <-> Pico Memory Peripheral Bus Bridge-----
OPBMemBridge
#(
   .C_OPB_AWIDTH(32),
   .C_OPB_DWIDTH(32),
   .C_BASEADDR  (`OPB_BUSBRIDGE_BASEADDR),
   .C_HIGHADDR  (`OPB_BUSBRIDGE_HIGHADDR)
)
OPBMemBridge(
   .Clk200          (Clk200),
   .MemAddr         (MemAddrMaster),
   .MemDIn          (DataIn),
   .MemDOut         (DataOut),
   .IOReadMaster    (IOReadMaster),
   .IOWriteMaster   (IOWriteMaster),
   .MemReadMaster   (MemReadMaster),
   .MemWriteMaster  (MemWriteMaster),
   .AttrReadMaster  (AttrReadMaster),
   .AttrWriteMaster (AttrWriteMaster),
   .MemWait         (MemWait),
   .OPB_Clk         (OPB_Clk),             // opb -> slave bus
   .OPB_Clk90       (OPB_Clk90),
   .OPB_Rst         (OPB_Rst),
   .OPB_ABus        (OPB_ABus),
   .OPB_BE          (OPB_BE),
   .OPB_DBus        (OPB_DBus),
   .OPB_RNW         (OPB_RNW),
   .OPB_select      (OPB_select),
   .OPB_seqAddr     (OPB_seqAddr),
   .Sl_DBus         (MB_Sl_DBus),      // slave -> opb bus
   .Sl_errAck       (MB_Sl_errAck),
   .Sl_retry        (MB_Sl_retry),
   .Sl_toutSup      (MB_Sl_toutSup),
   .Sl_xferAck      (MB_Sl_xferAck)
   ,.test_pins      (test_pins[95:0])
);


//------------------------------------------------------------
/*
 * keyhole module bridges access between the cf and opb bus for basic
 * communication and data transfer through 2 32-bit shared registers
 */

`ifdef ENABLE_KEYHOLE
Keyhole
#(
   .C_OPB_AWIDTH(`C_OPB_AWIDTH),
   .C_OPB_DWIDTH(`C_OPB_DWIDTH),
   .C_BASEADDR  (`OPB_KEYHOLE_BASEADDR)
)
Keyhole(
   .IOAddress   (IOAddr[`PCMCIA_ADR_LINES-1:0]),   // cf bus
   .din         (CFDataIn[15:0]),
   .dout        (KeyholeDataOut[15:0]),
   .CFIORead    (CFIORead),
   .CFIOWrite   (CFIOWrite),
   .OPB_Clk     (OPB_Clk),                        // opb -> slave bus
   .OPB_Clk90   (OPB_Clk90),
   .sys_rst     (OPB_Rst),                        //gme: sys_rst),//hrgt: OPB_Rst),
   .OPB_ABus    (OPB_ABus),                       //opb -> slave bus
   .OPB_BE      (OPB_BE),                         //       "  
   .OPB_DBus    (OPB_DBus),                       //       "  
   .OPB_RNW     (OPB_RNW),                        //       "  
   .OPB_select  (OPB_select),                     //       "  
   .OPB_seqAddr (OPB_seqAddr),                    //       "  
   .Sl_DBus     (Kh_Sl_DBus[0:31]),               // slave <- opb bus
   .Sl_errAck   (Kh_Sl_errAck),                   //       " 
   .Sl_retry    (Kh_Sl_retry),                    //       "
   .Sl_toutSup  (Kh_Sl_toutSup),                  //       "
   .Sl_xferAck  (Kh_Sl_xferAck)                   //       "
   //,.test_pins()
);
`endif

//-------------- PPC functions -----------------------------
wire Cap_Sl_errAck, Cap_Sl_retry, Cap_Sl_toutSup, Cap_Sl_xferAck;
wire [31:0] Cap_Sl_DBus;
PPC_FUNCTIONS PPCfunctions
 (.OPB_Clk(OPB_Clk), 
  .OPB_ABus(OPB_ABus), .OPB_RNW(OPB_RNW), .OPB_DBus(OPB_DBus), //OPB -> Slave Signals  
  .OPB_select(OPB_select),                                     //       "  
  .StandaloneSw(StandaloneSw),                                 //hrgt June 6 29, 07 RFUi added for standalone detection
  .FLASH_AIN(FLASH_AIN),                                       //for peekaboo port    //hrgt: Jan 25, 07
  .CPLD_PEEKABOO_PPC(CPLD_PEEKABOO_PPC), 
  .CPLD_RELOAD_PPC(CPLD_RELOAD_PPC),                           //for peekaboo port //hrgt: Jan 25, 07
  .Sl_DBus(Cap_Sl_DBus),                                       //Slave -> OPB Signals
  .Sl_errAck(Cap_Sl_errAck),  .Sl_retry(Cap_Sl_retry),         //       "
  .Sl_toutSup(Cap_Sl_toutSup),.Sl_xferAck(Cap_Sl_xferAck)      //       "
 );

wire Int_Sl_errAck;
wire Int_Sl_retry;
wire Int_Sl_toutSup;
wire Int_Sl_xferAck;
wire [31:0] Int_Sl_DBus;
INTERRUPT_MAPPER Interrupt_mapper
 (
   .OPB_ABus(OPB_ABus),
   .OPB_RNW(OPB_RNW),                      //OPB -> Slave Signals    
   .Sl_DBus(Int_Sl_DBus),                  //Slave -> OPB Signals
   .Sl_errAck(Int_Sl_errAck),
   .Sl_retry(Int_Sl_retry),                //       "
   .Sl_toutSup(Int_Sl_toutSup),
   .Sl_xferAck(Int_Sl_xferAck)             //       "
 );

//assign test_pins[127] = CPUMemMaster;

//------------------------ User module if specified ------------------------------------------------
//Following ifdef allows user to include an additional module which can see the CF bus and the PPC bus.
//See samples\E12_counter\firmware. If you need multiple modules, replicate this logic to suite your needs.
`ifdef ENABLE_USER_PPCSYSTEM_MODULE
  wire [15:0]UM_CF_dataOut;
  `UserModulePPCsystem `UserModulePPCsystem 
  (.IORead     (IORead),                                  //Cardbus signals 
   .IOWrite    (IOWrite), 
   .IOAddress  (IOAddr[`PCMCIA_ADR_LINES-1:0]),
   .din        (CFDataIn[15:0]), 
   .dout       (UM_CF_dataOut[15:0]),                       //OPB -> Slave Signals
   .OPB_Clk    (OPB_Clk), 
   .sys_rst    (OPB_Rst), 
   .OPB_ABus   (OPB_ABus), 
   .OPB_DBus   (OPB_DBus), 
   .OPB_RNW    (OPB_RNW),                                //Slave -> OPB Signals    
   .Sl_DBus    (UM_Sl_DBus), 
   .Sl_errAck  (UM_Sl_errAck), 
   .Sl_retry   (UM_Sl_retry), 
   .Sl_toutSup (UM_Sl_toutSup),
   .Sl_xferAck (UM_Sl_xferAck));
`endif //} ENABLE_USER_PPCSYSTEM_MODULE...

assign Sl_DBus =    `ifdef ENABLE_USER_MODULE_PPCSYSTEM UM_Sl_DBus     | `endif 
                    `ifdef ENABLE_KEYHOLE               Kh_Sl_DBus     | `endif
                                                        MB_Sl_DBus     | Ctrl_Sl_DBus    |  Int_Sl_DBus    |  Cap_Sl_DBus    | Sl_DBus_ext;

assign Sl_errAck =  `ifdef ENABLE_USER_MODULE_PPCSYSTEM UM_Sl_errAck   | `endif 
                    `ifdef ENABLE_KEYHOLE               Kh_Sl_errAck   | `endif
                                                        MB_Sl_errAck   | Ctrl_Sl_errAck  |  Int_Sl_errAck  |  Cap_Sl_errAck  | Sl_errAck_ext;

assign Sl_retry =   `ifdef ENABLE_USER_MODULE_PPCSYSTEM UM_Sl_retry    | `endif 
                    `ifdef ENABLE_KEYHOLE               Kh_Sl_retry    | `endif
                                                        MB_Sl_retry    | Ctrl_Sl_retry   |  Int_Sl_retry   |  Cap_Sl_retry   | Sl_retry_ext;

assign Sl_toutSup = `ifdef ENABLE_USER_MODULE_PPCSYSTEM UM_Sl_toutSup  | `endif 
                    `ifdef ENABLE_KEYHOLE               Kh_Sl_toutSup  | `endif
                                                        MB_Sl_toutSup  | Ctrl_Sl_toutSup |  Int_Sl_toutSup |  Cap_Sl_toutSup | Sl_toutSup_ext;

assign Sl_xferAck = `ifdef ENABLE_USER_MODULE_PPCSYSTEM UM_Sl_xferAck  | `endif 
                    `ifdef ENABLE_KEYHOLE               Kh_Sl_xferAck  | `endif
                                                        MB_Sl_xferAck  | Ctrl_Sl_xferAck |  Int_Sl_xferAck |  Cap_Sl_xferAck | Sl_xferAck_ext;

assign CFDataOut  = `ifdef ENABLE_USER_MODULE_PPCSYSTEM UM_CF_dataOut  | `endif 
                    `ifdef ENABLE_KEYHOLE               KeyholeDataOut | `endif
                                                        16'h0;

assign PicoDataOut = 31'h0;

`ifdef ENABLE_DEBUG_TAPS
wire [100:0] keeper;
//synthesis attribute KEEP of keeper is TRUE;
DebugTap #(.Width(16)) CF_DataIn_Tap   (CFDataIn[15:0],   keeper[0]);
DebugTap #(.Width(32)) OPB_ABus_Tap    (OPB_ABus,         keeper[1]);
DebugTap #(.Width(2))  OPB_BE_Tap      (OPB_BE,           keeper[2]);
DebugTap #(.Width(32)) OPB_DBus_Tap    (OPB_DBus,         keeper[3]);
DebugTap #(.Width(1))  OPB_RNW_Tap     (OPB_RNW,          keeper[4]);
DebugTap #(.Width(1))  OPB_Select_Tap  (OPB_select,       keeper[5]);
DebugTap #(.Width(32)) Sl_DBus_Tap     (Kh_Sl_DBus[0:31], keeper[7]);
DebugTap #(.Width(1))  OPB_Clk_Tap     (OPB_Clk,          keeper[8]);
DebugTap #(.Width(1))  DRP_IOWrite_Tap (IOWrite,          keeper[9]);
DebugTap #(.Width(1))  DRP_IORead_Tap  (IORead,           keeper[10]);
DebugTap #(.Width(16)) DRP_IOAddr_Tap  (IOAddr,           keeper[11]);          
`endif // ENABLE_DEBUG_TAPS

endmodule
